import hashlib, os, tempfile, traceback

DIGEST_BUFFER_SIZE = 102400

def calc_digest(path):
    m = hashlib.md5()
    f = file(path, 'rb')
    inbytes = f.read(DIGEST_BUFFER_SIZE)
    while len(inbytes) > 0:
        m.update(inbytes)
        inbytes = f.read(10240)
    return m.hexdigest()

def get_configfile_in_stream(stream, filename):
    return db((db.configfile.stream == stream.id) & (db.configfile.filename == filename)).select().first()

@service.xmlrpc
def get_algorithms():
    db_algorithms = db(db.algorithm.id > 0).select()
    algorithms = []
    for alg in db_algorithms:
        algorithms.append((alg.name, alg.description))
    return algorithms

@service.xmlrpc
def get_file_digest(token, filename, digest):
    token = db(db.uploadtoken.token == token).select().first()
    if token:
        if token.expiration_date > datetime.datetime.now():
            stream = token.stream
            configfile = get_configfile_in_stream(stream, filename)
            if configfile:
                return calc_digest(os.path.join(request.folder,'uploads',configfile.file))
            else:
                return None
        else:
            return 'invalid token: expired token'
    else:
        return 'invalid token: unknown token'

@service.xmlrpc
def upload(token, filename, process, algorithm, binary_data):
    token = db(db.uploadtoken.token == token).select().first()
    if token:
        if token.expiration_date < datetime.datetime.now():
            return 'invalid token: expired token'
        stream = token.stream
        configfile = get_configfile_in_stream(stream, filename)
        tmpname = os.path.join(request.folder, 'uploads', uuid.uuid4().hex)
        tmp = open(tmpname, 'w')
        tmp.write(binary_data.data)
        tmp.close()
        tmp = open(tmpname, 'rb')
        #print db.configfile.file.requires
        error_message = db.configfile.file.validate(tmp)
        #print error_message
        if configfile:
            configfile.update_record(file=db.configfile.file.store(tmp, filename))
        else:
            new_id = db.configfile.insert(stream=stream, filename=filename, posted_by=stream.posted_by, file=db.configfile.file.store(tmp, filename))
            tmp.close()
        db.commit()
        os.remove(tmpname)
        if not configfile:
            configfile = db(db.configfile.id == new_id).select().first()
        if process:
            db.processedfile.insert(configfile=configfile, algorithm=algorithm, posted_by=configfile.posted_by, status='queued')
        return 'ok'
    else:
        return 'invalid token: unknown token'
